# Copyright 2025 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("//pw_bloat:pw_cc_size_binary.bzl", "pw_cc_size_binary")
load("//pw_bloat:pw_size_diff.bzl", "pw_size_diff")
load("//pw_bloat:pw_size_table.bzl", "pw_size_table")

package(
    default_visibility = ["//visibility:public"],
    features = ["-ctad_warnings"],
)

licenses(["notice"])

cc_library(
    name = "size_report",
    srcs = ["size_report.cc"],
    hdrs = ["public/pw_async2/size_report/size_report.h"],
    strip_include_prefix = "public",
    deps = [
        "//pw_allocator:allocator",
        "//pw_allocator:first_fit",
        "//pw_async2:dispatcher",
        "//pw_async2:pendable",
        "//pw_bloat:bloat_this_binary",
        "//pw_containers:intrusive_forward_list",
        "//pw_log",
        "//pw_preprocessor",
        "//pw_sync:interrupt_spin_lock",
        "//pw_sync:mutex",
        "//pw_sync:thread_notification",
    ],
)

pw_cc_size_binary(
    name = "empty_base",
    srcs = ["base.cc"],
    deps = [
        ":size_report",
        "//pw_bloat:bloat_this_binary",
    ],
)

pw_cc_size_binary(
    name = "async2_core",
    srcs = ["async2_core.cc"],
    deps = [
        ":size_report",
        "//pw_assert:check",
        "//pw_async2:dispatcher",
        "//pw_async2:pendable",
        "//pw_bloat:bloat_this_binary",
    ],
)

pw_cc_size_binary(
    name = "async2_core_additional_task",
    srcs = ["async2_core.cc"],
    defines = ["_PW_ASYNC2_SIZE_REPORT_INCREMENTAL_TASK=1"],
    deps = [
        ":size_report",
        "//pw_assert:check",
        "//pw_async2:dispatcher",
        "//pw_async2:pendable",
        "//pw_bloat:bloat_this_binary",
    ],
)

pw_cc_size_binary(
    name = "async2_core_once_sender",
    srcs = ["async2_core.cc"],
    defines = ["_PW_ASYNC2_SIZE_REPORT_ONCE_SENDER=1"],
    deps = [
        ":size_report",
        "//pw_assert:check",
        "//pw_async2:dispatcher",
        "//pw_async2:once_sender",
        "//pw_async2:pendable",
        "//pw_bloat:bloat_this_binary",
    ],
)

pw_cc_size_binary(
    name = "async2_core_once_sender_incremental",
    srcs = ["async2_core.cc"],
    defines = [
        "_PW_ASYNC2_SIZE_REPORT_ONCE_SENDER=1",
        "_PW_ASYNC2_SIZE_REPORT_ONCE_SENDER_INCREMENTAL=1",
    ],
    deps = [
        ":size_report",
        "//pw_assert:check",
        "//pw_async2:dispatcher",
        "//pw_async2:once_sender",
        "//pw_async2:pendable",
        "//pw_bloat:bloat_this_binary",
    ],
)

pw_cc_size_binary(
    name = "async2_core_coroutine",
    srcs = ["async2_core.cc"],
    defines = ["_PW_ASYNC2_SIZE_REPORT_COROUTINE=1"],
    deps = [
        ":size_report",
        "//pw_assert:check",
        "//pw_async2:coro",
        "//pw_async2:dispatcher",
        "//pw_async2:pendable",
        "//pw_bloat:bloat_this_binary",
    ],
)

pw_cc_size_binary(
    name = "select_size_report",
    srcs = ["select.cc"],
    defines = ["_PW_ASYNC2_SIZE_REPORT_SELECT=1"],
    deps = [
        ":size_report",
        "//pw_assert:check",
        "//pw_async2:dispatcher",
        "//pw_async2:pendable",
        "//pw_async2:select",
        "//pw_bloat:bloat_this_binary",
        "//pw_log",
    ],
)

pw_cc_size_binary(
    name = "incremental_select_size_report",
    srcs = ["select.cc"],
    defines = [
        "_PW_ASYNC2_SIZE_REPORT_SELECT=1",
        "_PW_ASYNC2_SIZE_REPORT_SELECT_INCREMENTAL=1",
    ],
    deps = [
        ":size_report",
        "//pw_assert:check",
        "//pw_async2:dispatcher",
        "//pw_async2:pendable",
        "//pw_async2:select",
        "//pw_bloat:bloat_this_binary",
        "//pw_log",
    ],
)

pw_cc_size_binary(
    name = "select_comparison_manual_size_report",
    srcs = ["select.cc"],
    defines = ["_PW_ASYNC_2_SIZE_REPORT_COMPARE_SELECT_MANUAL=1"],
    deps = [
        ":size_report",
        "//pw_assert:check",
        "//pw_async2:dispatcher",
        "//pw_async2:pendable",
        "//pw_async2:select",
        "//pw_bloat:bloat_this_binary",
        "//pw_log",
    ],
)

pw_cc_size_binary(
    name = "select_comparison_helper_size_report",
    srcs = ["select.cc"],
    defines = ["_PW_ASYNC_2_SIZE_REPORT_COMPARE_SELECT_HELPER=1"],
    deps = [
        ":size_report",
        "//pw_assert:check",
        "//pw_async2:dispatcher",
        "//pw_async2:pendable",
        "//pw_async2:select",
        "//pw_bloat:bloat_this_binary",
        "//pw_log",
    ],
)

pw_cc_size_binary(
    name = "join_size_report",
    srcs = ["join.cc"],
    defines = ["_PW_ASYNC2_SIZE_REPORT_JOIN=1"],
    deps = [
        ":size_report",
        "//pw_assert:check",
        "//pw_async2:dispatcher",
        "//pw_async2:join",
        "//pw_async2:pendable",
        "//pw_bloat:bloat_this_binary",
        "//pw_log",
    ],
)

pw_cc_size_binary(
    name = "incremental_join_size_report",
    srcs = ["join.cc"],
    defines = [
        "_PW_ASYNC2_SIZE_REPORT_JOIN=1",
        "_PW_ASYNC2_SIZE_REPORT_JOIN_INCREMENTAL=1",
    ],
    deps = [
        ":size_report",
        "//pw_assert:check",
        "//pw_async2:dispatcher",
        "//pw_async2:join",
        "//pw_async2:pendable",
        "//pw_bloat:bloat_this_binary",
        "//pw_log",
    ],
)

pw_size_diff(
    name = "full_size_report_row",
    base = ":empty_base",
    label = "Full cost of including pw_async2",
    target = ":async2_core",
)

pw_size_diff(
    name = "incremental_task_row",
    base = ":async2_core",
    label = "Base incremental cost of adding a task to an existing async system",
    target = ":async2_core_additional_task",
)

pw_size_diff(
    name = "once_sender_row",
    base = ":async2_core",
    label = "Size of OnceSender / OnceReceiver",
    target = ":async2_core_once_sender",
)

pw_size_diff(
    name = "incremental_once_sender_row",
    base = ":async2_core_once_sender",
    label = "Cost of additional OnceSender / OnceReceiver template specialization",
    target = ":async2_core_once_sender_incremental",
)

pw_size_diff(
    name = "coroutine_row",
    base = ":async2_core",
    label = "Size of pw_async2's C++ coroutine adapters",
    target = ":async2_core_coroutine",
)

pw_size_diff(
    name = "select_row",
    base = ":async2_core",
    label = "Size of calling Select() with several pendables of the same type",
    target = ":select_size_report",
)

pw_size_diff(
    name = "incremental_select_row",
    base = ":select_size_report",
    label = "Size of an additional a call to Select() with pendables of different types",
    target = ":incremental_select_size_report",
)

pw_size_diff(
    name = "select_comparison_row",
    base = ":select_comparison_manual_size_report",
    label = "Cost of using Select() versus manually polling each pendable",
    target = ":select_comparison_helper_size_report",
)

pw_size_diff(
    name = "join_row",
    base = ":async2_core",
    label = "Size of calling Join() with several pendables of the same type",
    target = ":join_size_report",
)

pw_size_diff(
    name = "incremental_join_row",
    base = ":join_size_report",
    label = "Size of an additional a call to Join() with pendables of different types",
    target = ":incremental_join_size_report",
)

pw_size_table(
    name = "full_size_report",
    reports = [
        ":full_size_report_row",
        ":incremental_task_row",
    ] + select({
        "//pw_toolchain/cc:c++20_enabled": [":coroutine_row"],
        "//conditions:default": [],
    }),
)

pw_size_table(
    name = "once_sender_size_report",
    reports = [
        ":once_sender_row",
        ":incremental_once_sender_row",
    ],
)

pw_size_table(
    name = "utilities_size_report",
    reports = [
        ":select_row",
        ":incremental_select_row",
        ":select_comparison_row",
        ":join_row",
        ":incremental_join_row",
    ],
)
